package com.fin.zw.intelligentbot.service;


import com.alibaba.fastjson.JSONObject;
import com.csvreader.CsvReader;
import com.fin.zw.intelligentbot.entity.Variable;
import com.fin.zw.intelligentbot.entity.*;
import com.fin.zw.intelligentbot.enums.Sex;
import com.fin.zw.intelligentbot.enums.TaskStatus;
import com.fin.zw.intelligentbot.enums.Whether;
import com.fin.zw.intelligentbot.job.TaskServiceJob;
import com.fin.zw.intelligentbot.model.ResulteWraper;
import com.fin.zw.intelligentbot.model.base.*;
import com.fin.zw.intelligentbot.model.request.DialTaskParamRequest;
import com.fin.zw.intelligentbot.model.request.DialTaskRequest;
import com.fin.zw.intelligentbot.model.request.TaskCustomerRequest;
import com.fin.zw.intelligentbot.model.request.TaskRecycleRequest;
import com.fin.zw.intelligentbot.model.response.DialTaskResponse;
import com.fin.zw.intelligentbot.model.session.SessionModel;
import com.fin.zw.intelligentbot.repository.*;
import com.fin.zw.intelligentbot.util.CSVUtils;
import com.fin.zw.intelligentbot.util.ExcelUtil;
import com.fin.zw.intelligentbot.util.FileUtil;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service("dialTaskService")
public class DialTaskService {

    private static final String[] sexFix = {"男", "male"};

    private static final Logger log = LoggerFactory.getLogger(DialTaskService.class);

    @Value("${root.template}")
    private String rootPath;

    @Autowired
    private DialTaskRepository dialTaskRepository;

    @Autowired
    private SceneInfoRepository sceneInfoRepository;

    @Autowired
    private RobotInfoRepository robotInfoRepository;

    @Autowired
    private TaskCustomerRepository taskCustomerRepository;

    @Autowired
    private StrategyInfoRespository strategyInfoRespository;

    @Autowired
    private CommonService commonService;

    @Autowired
    private UploadFileService uploadFileService;

    @Autowired
    private SocketService socketService;

    @Autowired
    TaskServiceJob taskServiceJob;

    @Autowired
    DialTaskImportRecordService importRecordService;

    @Autowired
    private BlacklistService blacklistService;

    /**
     * @param pageable
     * @param sessionModel
     * @return
     */
    public Page<DialTaskResponse> queryDialTaskAll(Pageable pageable, DialTaskParamRequest request, SessionModel sessionModel) throws Exception {
        BooleanBuilder builder = getBooleanBuilder(request, sessionModel);

        Page<DialTask> dialTaskPage = dialTaskRepository.findAll(builder, pageable);

        Page<DialTaskResponse> page = dialTaskPage.map(dialTask -> {
            DialTaskResponse response = getDialTaskResponse(dialTask);
            return response;
        });
        return page;
    }

    /**
     * 数据类型转换
     *
     * @param dialTask
     * @return
     */
    public DialTaskResponse getDialTaskResponse(DialTask dialTask) {
        DialTaskResponse response = new DialTaskResponse();
        BeanUtils.copyProperties(dialTask, response);
        response.setCustomerDataFile(dialTask.getCustomerDataFile());
        Integer connectCount = setDialTaskResponse(dialTask, TaskStatus.CONNECTED);
        response.setConnectCount(connectCount);//电话接通数量
        BooleanBuilder builder = new BooleanBuilder();
        builder.and(QTaskCustomer.taskCustomer.status.in(TaskStatus.READY, TaskStatus.NEW));
        builder.and(QTaskCustomer.taskCustomer.dialTask.id.eq(dialTask.getId()));
        Long count = taskCustomerRepository.count(builder);
        Integer newCall = count.intValue();
        response.setCalledCount(dialTask.getCount() - newCall);
        return response;
    }

    public BooleanBuilder getBooleanBuilder(DialTaskParamRequest request, SessionModel sessionModel) throws Exception {
        BooleanBuilder builder = new BooleanBuilder();
        QDialTask qDialTask = QDialTask.dialTask;
        if (StringUtils.isNotEmpty(sessionModel.getCompanyId())) {
            if (commonService.whetherAdmin(sessionModel)) {
                builder.and(qDialTask.company.id.eq(sessionModel.getCompanyId()));
            } else {
                builder.and(qDialTask.createId.eq(sessionModel.getUserId()));
            }
        }
        if (request.getName() != null && !"".equals(request.getName())) {
            builder.and(qDialTask.name.contains(request.getName()));
        }
        if (StringUtils.isNotEmpty(request.getScene())) {
            builder.and(qDialTask.scene.id.eq(request.getScene()));
        }
        if (request.getStartTime() != null && request.getEndTime() != null) {
            builder.and(qDialTask.createTime.between(request.getStartTime(), request.getEndTime()));
        }
        if (request.getStatus() != null) {
            builder.and(qDialTask.status.eq(request.getStatus()));
        }
        return builder;
    }

    public List<DialTaskResponse> fetchApi(DialTaskParamRequest request, SessionModel sessionModel) throws Exception {
        BooleanBuilder builder = getBooleanBuilder(request, sessionModel);
        if (StringUtils.isNotEmpty(request.getId())) {
            builder.and(QDialTask.dialTask.id.eq(request.getId()));
        }
        Iterator<DialTask> iterator = dialTaskRepository.findAll(builder).iterator();
        List<DialTask> dialTasks = Lists.newArrayList(iterator);
        List<DialTaskResponse> list = dialTasks.stream().map(task -> {
            DialTaskResponse response = getDialTaskResponse(task);
            return response;
        }).collect(Collectors.toList());
        return list;
    }


    /**
     * 获取简化信息的任务信息
     *
     * @param request
     * @param sessionModel
     * @return
     */
    public List<PushTask> fetchSimplifyTask(DialTaskParamRequest request, SessionModel sessionModel) {
        List<PushTask> tasks = new ArrayList<>();
        BooleanBuilder tcCondition = new BooleanBuilder();
        if (StringUtils.isNotEmpty(sessionModel.getCompanyId())) {
            tcCondition.and(QTaskCustomer.taskCustomer.dialTask.createId.eq(sessionModel.getUserId()));
        } else {
            tcCondition.and(QTaskCustomer.taskCustomer.dialTask.id.isNotNull());
        }
        generateTaskCondition(request, tcCondition);
        if (request.getPhoneStatus() != null) {
            tcCondition.and(QTaskCustomer.taskCustomer.status.eq(request.getPhoneStatus()));
        }
        if (StringUtils.isNotBlank(request.getPhone())) {
            tcCondition.and(QTaskCustomer.taskCustomer.phone.eq(request.getPhone()));
        }
        if (StringUtils.isNotBlank(request.getCustomerName())) {
            tcCondition.and(QTaskCustomer.taskCustomer.name.contains(request.getCustomerName()));
        }
        Iterator<TaskCustomer> iterator = taskCustomerRepository.findAll(tcCondition).iterator();
        List<TaskCustomer> list = Lists.newArrayList(iterator);
        Map<DialTask, List<TaskCustomer>> taskGroup = list.stream().collect(Collectors.groupingBy(TaskCustomer::getDialTask));
        for (Map.Entry<DialTask, List<TaskCustomer>> entry : taskGroup.entrySet()) {
            PushTask pushTask = new PushTask();
            DialTask dialTask = entry.getKey();
            CompanyInfo companyInfo = new CompanyInfo();
            BeanUtils.copyProperties(dialTask.getCompany(), companyInfo);
            BeanUtils.copyProperties(dialTask, pushTask);
            pushTask.setCompanyInfo(companyInfo);
            pushTask.setStatus(dialTask.getStatus().toString());
            Scene scene = new Scene();
            BeanUtils.copyProperties(dialTask.getScene(), scene);
            pushTask.setScene(scene);
            List<PushRobot> pushRobots = new ArrayList<>();
            for (RobotInfo robotInfo : dialTask.getRobots()) {
                PushRobot pushRobot = new PushRobot();
                BeanUtils.copyProperties(robotInfo, pushRobot);
                AiConfigura nlp = new AiConfigura();
                BeanUtils.copyProperties(robotInfo.getNlp(), nlp);
                AiAccountBase nlpAccount = new AiAccountBase();
                BeanUtils.copyProperties(robotInfo.getNlp().getAccounts(), nlpAccount);
                nlp.setAccount(nlpAccount);
                pushRobot.setNlp(nlp);
                AiConfigura asr = new AiConfigura();
                BeanUtils.copyProperties(robotInfo.getAsr(), asr);
                AiAccountBase asrAccount = new AiAccountBase();
                BeanUtils.copyProperties(robotInfo.getAsr().getAccounts(), asrAccount);
                asr.setAccount(asrAccount);
                pushRobot.setAsr(asr);
                AiConfigura tts = new AiConfigura();
                BeanUtils.copyProperties(robotInfo.getTts(), tts);
                AiAccountBase ttsAccount = new AiAccountBase();
                BeanUtils.copyProperties(robotInfo.getTts().getAccounts(), ttsAccount);
                tts.setAccount(ttsAccount);
                pushRobot.setTts(tts);
                Category category = new Category();
                BeanUtils.copyProperties(robotInfo.getGateway(), category);
                pushRobot.setGateway(category);
                pushRobots.add(pushRobot);
            }
            pushTask.setRobots(pushRobots);
            tasks.add(pushTask);
        }
        return tasks;
    }

    public Map<DialTask, List<TaskCustomer>> fetch(DialTaskParamRequest request, SessionModel sessionModel) {
        List<DialTaskResponse> tasks = new ArrayList<>();

        BooleanBuilder tcCondition = new BooleanBuilder();

        if (StringUtils.isNotEmpty(sessionModel.getCompanyId())) {
            tcCondition.and(QTaskCustomer.taskCustomer.dialTask.createId.eq(sessionModel.getUserId()));
        } else {
            tcCondition.and(QTaskCustomer.taskCustomer.dialTask.id.isNotNull());
        }

        generateTaskCondition(request, tcCondition);

        generateTaskCustomerCondition(request, tcCondition);

        List<TaskCustomer> customers = Lists.newArrayList(this.taskCustomerRepository.findAll(tcCondition).iterator());

        //此处有待验证正用对象做键是否有问题
        Map<DialTask, List<TaskCustomer>> taskGroup = customers.stream().collect(Collectors.groupingBy(TaskCustomer::getDialTask));

        return taskGroup;
    }

    private void generateTaskCustomerCondition(DialTaskParamRequest request, BooleanBuilder tcCondition) {

        Boolean hasTCCondition = false;

        if (request.getPhoneStatus() != null) {
            tcCondition.and(QTaskCustomer.taskCustomer.status.eq(request.getPhoneStatus()));
        }

        if (StringUtils.isNotBlank(request.getPhone())) {
            tcCondition.and(QTaskCustomer.taskCustomer.phone.eq(request.getPhone()));
        }

        if (StringUtils.isNotBlank(request.getCustomerName())) {
            tcCondition.and(QTaskCustomer.taskCustomer.name.contains(request.getCustomerName()));
        }
    }

    private void generateTaskCondition(DialTaskParamRequest request, BooleanBuilder taskCondition) {

        if (request.getStatus() != null) {
            taskCondition.and(QTaskCustomer.taskCustomer.dialTask.status.eq(request.getStatus()));
        }

        if (request.getId() != null && !"".equals(request.getId())) {
            taskCondition.and(QTaskCustomer.taskCustomer.dialTask.id.eq(request.getId()));
        }

        if (request.getName() != null && !"".equals(request.getName())) {
            taskCondition.and(QTaskCustomer.taskCustomer.dialTask.name.contains(request.getName()));
        }
        if (request.getScene() != null && !"".equals(request.getScene())) {
            taskCondition.and(QTaskCustomer.taskCustomer.dialTask.scene.id.eq(request.getScene()));
        }
    }


    /**
     * 统计电话状态数量
     *
     * @param task
     * @return
     */
    public Integer setDialTaskResponse(DialTask task, TaskStatus taskStatus) {
        BooleanBuilder builder = new BooleanBuilder();
        builder.and(QTaskCustomer.taskCustomer.status.eq(taskStatus));
        builder.and(QTaskCustomer.taskCustomer.dialTask.id.eq(task.getId()));
        Long count = taskCustomerRepository.count(builder);
        return count.intValue();
    }


    /**
     * 任务创建
     *
     * @param request
     * @param sessionModel
     */
    @Transactional
    public DialTask createDialTask(DialTaskRequest request, SessionModel sessionModel, ResulteWraper wraper) throws Exception {
        if (sessionModel.getCompanyId() == null) {
            log.info("管理人员不允许添加任务");
            throw new RuntimeException("管理人员不允许添加任务");
        }
        DialTask task = this.createTask(request);

        task.setCreateId(sessionModel.getUserId());

        Company company = commonService.getCompany(sessionModel);
        task.setCompany(company);

        task.setScene(sceneInfoRepository.findById(request.getScene()).get());

        if (StringUtils.isNotEmpty(request.getStrategyId())) {
            Optional<StrategyInfo> optional = strategyInfoRespository.findById(request.getStrategyId());
            if (optional.isPresent()) {
                task.setStrategyInfo(optional.get());
            }
        }

        if (request.getRobots() != null && request.getRobots().size() > 0) {
            Iterator<RobotInfo> robots = robotInfoRepository
                    .findAll(QRobotInfo.robotInfo.id.in(request.getRobots()))
                    .iterator();
            task.setRobots(new HashSet<>(Lists.newArrayList(robots)));
        } else {   //如果调用方没有给机器人，则默认使用该企业下所有机器人
            Iterator<RobotInfo> robots = robotInfoRepository
                    .findAll(QRobotInfo.robotInfo.company.id.eq(sessionModel.getCompanyId())).iterator();
            task.setRobots(new HashSet<>(Lists.newArrayList(robots)));
        }

        task.setStatus(request.getAutoExecute() ? TaskStatus.READY : TaskStatus.NEW);

        List<TaskCustomer> tcs = this.createTaskCustomers(request, task, company);

        task.setCount(tcs.size());
        BooleanBuilder builder = new BooleanBuilder();
        QDialTask qDialTask = QDialTask.dialTask;
        builder.and(qDialTask.name.eq(task.getName()));
        builder.and(qDialTask.count.eq(task.getCount()));
        Iterator<DialTask> iterator = dialTaskRepository.findAll(builder).iterator();
        if (iterator.hasNext()) {
            wraper.setCode("500");
            wraper.setMsg("创建任务失败，该任务已经存在！");
        } else {
            dialTaskRepository.save(task);
            taskCustomerRepository.saveAll(tcs);

            // 信息导入回收日志记录 add 20200330 ZGQ
            DialTaskImportRecord importRecord = new DialTaskImportRecord();
            importRecord.setTaskName(task.getName());
            importRecord.setImportCount(task.getCount());
            importRecord.setErrorCount(task.getCount() - tcs.size());
            importRecord.setUserId(sessionModel.getUserId());
            importRecord.setUserName(sessionModel.getUserName());
            importRecord.setImportDate(new Date());
            importRecordService.save(importRecord);

            // 设置任务执行形式
            if (task.getAutoType().equals(Whether.YES)) {
                //设置定时任务
                if (task.getTiming() != null) {
                    taskServiceJob.start(task.getId());
                }
            } else {
                if (request.getAutoExecute()) {
                    task.setStartTime(new Date());
                    dialTaskRepository.save(task);

                    //todo  execute task,调用websocket将任务加入到机器人得呼叫队列。
                    //暂时不进行推送，让机器人主动拉取，因此此处可暂时不实现。
                    socketService.sendTaskInfoById(task.getId());
                }
            }
        }
        return task;
    }

    /**
     * 任务创建（针对上海电信定制化接口）
     *
     * @param request
     * @param sessionModel
     */
    @Async
    @Transactional(rollbackFor = Exception.class)
    public DialTask createDialTask(DialTaskRequest request, SessionModel sessionModel) throws Exception {
        if (sessionModel.getCompanyId() == null) {
            log.info("管理人员不允许添加任务");
            throw new RuntimeException("管理人员不允许添加任务");
        }
        DialTask task = this.createTask(request);
        task.setCreateId(sessionModel.getUserId());
        Company company = commonService.getCompany(sessionModel);
        task.setCompany(company);
        task.setScene(sceneInfoRepository.findById(request.getScene()).get());
        if (StringUtils.isNotEmpty(request.getStrategyId())) {
            Optional<StrategyInfo> optional = strategyInfoRespository.findById(request.getStrategyId());
            if (optional.isPresent()) {
                task.setStrategyInfo(optional.get());
            }
        }

        if (request.getRobots() != null && request.getRobots().size() > 0) {
            Iterator<RobotInfo> robots = robotInfoRepository
                    .findAll(QRobotInfo.robotInfo.id.in(request.getRobots()))
                    .iterator();
            task.setRobots(new HashSet<>(Lists.newArrayList(robots)));
        } else {   //如果调用方没有给机器人，则默认使用该企业下所有机器人
            Iterator<RobotInfo> robots = robotInfoRepository
                    .findAll(QRobotInfo.robotInfo.company.id.eq(sessionModel.getCompanyId())).iterator();
            task.setRobots(new HashSet<>(Lists.newArrayList(robots)));
        }

        task.setStatus(request.getAutoExecute() ? TaskStatus.READY : TaskStatus.NEW);
        List<TaskCustomer> tcs = this.createTaskCustomers(request, task, company);
        task.setCount(tcs.size());
        BooleanBuilder builder = new BooleanBuilder();
        QDialTask qDialTask = QDialTask.dialTask;
        builder.and(qDialTask.name.eq(task.getName()));
        builder.and(qDialTask.count.eq(task.getCount()));
        Iterator<DialTask> iterator = dialTaskRepository.findAll(builder).iterator();
        if (iterator.hasNext()) {
            log.error("创建任务失败，该任务已经存在！");
        } else {
            task = dialTaskRepository.save(task);
            taskCustomerRepository.saveAll(tcs);
            // 信息导入回收日志记录 add 20200330 ZGQ
            DialTaskImportRecord importRecord = new DialTaskImportRecord();
            importRecord.setTaskName(task.getName());
            importRecord.setImportCount(task.getCount());
            importRecord.setErrorCount(task.getCount() - tcs.size());
            importRecord.setUserId(sessionModel.getUserId());
            importRecord.setUserName(sessionModel.getUserName());
            importRecord.setImportDate(new Date());
            importRecordService.save(importRecord);
            // 设置任务执行形式
            if (task.getAutoType().equals(Whether.YES)) {
                //设置定时任务
                if (task.getTiming() != null) {
                    taskServiceJob.start(task.getId());
                }
            } else {
                if (request.getAutoExecute()) {
                    task.setStartTime(new Date());
                    dialTaskRepository.save(task);
                    //todo  execute task,调用websocket将任务加入到机器人得呼叫队列。
                    //暂时不进行推送，让机器人主动拉取，因此此处可暂时不实现。
                    socketService.sendTaskInfoById(task.getId());
                }
            }
        }
        return task;
    }

    private List<TaskCustomer> createTaskCustomers(DialTaskRequest request, DialTask task, Company company) throws Exception {
        if (request.getCustomerDataFile() != null) {
            return this.createTaskCustomersFromFile(request.getCustomerDataFile(), task, company);
        } else {
            return this.createTaskCustomersFromDatas(request.getCustomers(), task, company);
        }
    }

    private List<TaskCustomer> createTaskCustomersFromFile(UploadFile file, DialTask task, Company company) throws Exception {
        List<TaskCustomer> taskCustomers = new ArrayList<>();
        if (file != null) {
            List<Map<String, String>> mapData = this.parseCSV(task.getCustomerDataFile());
            task.setCount(mapData.size());
            for (Map<String, String> line : mapData) {
                String jsonString = JSONObject.toJSON(line).toString();
                if (line.containsKey("phone") && StringUtils.isNotBlank(line.get("phone"))
                        && line.get("phone").length() > 10 && !line.get("phone").contains("*")) {
                    TaskCustomer tc = createTaskCustomer(line, jsonString);
                    tc.setDialTask(task);
                    tc.setCompany(company);
                    tc.setCreateTime(new Date());
                    tc.setStatus(task.getStatus());//将号码得状态跟任务状态设置为相同
                    String id = UUID.randomUUID().toString();
                    tc.setId(id);
                    tc.setScene(task.getScene());
                    taskCustomers.add(tc);
                }
            }
        }
        return taskCustomers;
    }

    private List<TaskCustomer> createTaskCustomersFromDatas(List<TaskCustomerRequest> customers, DialTask task, Company company) {
        List<TaskCustomer> taskCustomers = new ArrayList<>();
        if (customers != null)
            customers.forEach(c ->
            {
                if (!c.getPhone().contains("*") && c.getPhone().length() > 10) {
                    TaskCustomer tc = new TaskCustomer();
                    BeanUtils.copyProperties(c, tc);
                    tc.setDialTask(task);
                    tc.setCompany(company);
                    tc.setSex(this.analySex(c.getSex(), true));
                    tc.setStatus(task.getStatus());//将号码得状态跟任务状态设置为相同
                    tc.setCreateTime(new Date());
                    String id = UUID.randomUUID().toString();
                    tc.setId(id);
                    tc.setScene(task.getScene());
                    if (blacklistService.exitBlackListByPhone(tc.getPhone())) {
                        tc.setBlacklist(Whether.YES);
                    }
                    taskCustomers.add(tc);
                }
            });
        return taskCustomers;
    }

    private TaskCustomer createTaskCustomer(Map<String, String> line, String jsonString) {
        TaskCustomer tc = new TaskCustomer();
        tc.setName(line.containsKey("name") ? line.get("name") : "");
        tc.setPhone(line.containsKey("phone") ? line.get("phone") : "");
        tc.setIdCard(line.containsKey("idCard") ? line.get("idCard") : "");
        tc.setVariable(jsonString);
        tc.setCreateTime(new Date());
        Boolean isSex = line.containsKey("sex");
        String sexStr = isSex ? line.get("sex").trim() : tc.getIdCard();
        tc.setSex(this.analySex(sexStr, isSex));
        if (blacklistService.exitBlackListByPhone(tc.getPhone())) {
            tc.setBlacklist(Whether.YES);
        }
        return tc;
    }

    private Sex analySex(String str, Boolean isSex) {
        if ("".equals(str))
            return Sex.MALE;
        if (!isSex) {
            String icCard = str.trim();
            boolean sex = Integer.valueOf(icCard.substring(icCard.length() - 2, icCard.length() - 1)) % 2 == 0;
            return sex ? Sex.FEMALE : Sex.MALE;
        } else {
            return Arrays.asList(sexFix).contains(str.toLowerCase()) ? Sex.MALE : Sex.FEMALE;
        }
    }

    private DialTask createTask(DialTaskRequest reqTask)throws Exception {
        DialTask task = new DialTask();
        task.setName(reqTask.getName());
        task.setStatus(TaskStatus.NEW);
        task.setCreateTime(new Date());
        if(StringUtils.isNotBlank(reqTask.getTiming())){
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            task.setTiming(sf.parse(reqTask.getTiming()));
        }
        task.setCustomerDataFile(reqTask.getCustomerDataFile());
        return task;
    }


    /**
     * 任务的修改
     *
     * @param request
     * @param sessionModel
     * @throws Exception
     */
    public void updateDialTask(DialTaskRequest request, SessionModel sessionModel) throws Exception {

        DialTask task = dialTaskRepository.findById(request.getId()).get();

        if (StringUtils.isNotEmpty(request.getName())) {
            task.setName(request.getName());
        }

        if (StringUtils.isNotEmpty(request.getStatus())) {
            task.setStatus(TaskStatus.valueOf(request.getStatus()));
            if (task.getStatus().equals(TaskStatus.EXCUTING)) {
                task.setStartTime(new Date());
            } else if (task.getStatus().equals(TaskStatus.READY)) {
                BooleanBuilder excCondtion = new BooleanBuilder();
                excCondtion.and(QTaskCustomer.taskCustomer.dialTask.id.eq(request.getId()));
                Iterable<TaskCustomer> itcs = this.taskCustomerRepository.findAll(excCondtion);
                List<TaskCustomer> exctcs = IterableUtils.toList(itcs);
                exctcs.forEach(tc -> tc.setStatus(task.getStatus()));
                this.taskCustomerRepository.saveAll(exctcs);
            } else if (task.getStatus().equals(TaskStatus.FINISH)) {//任务完成
                task.setEndTime(new Date());
            }
        }

        if (StringUtils.isNotEmpty(request.getScene())) {
            task.setScene(sceneInfoRepository.findById(request.getScene()).get());
        }

        if (request.getRobots() != null && request.getRobots().size() > 0) {
            Iterable<RobotInfo> infos = robotInfoRepository.findAll(QRobotInfo.robotInfo.id.in(request.getRobots()));
            task.setRobots(new HashSet<>(IterableUtils.toList(infos)));
        }

        if (task.getStatus().equals(TaskStatus.NEW)) {
            if (request.getIsFileChanged()) {
                //修改任务数据
                Company company = commonService.getCompany(sessionModel);
                List<TaskCustomer> newCustomers = this.createTaskCustomers(request, task, company);
                task.setCount(newCustomers.size());
                taskCustomerRepository.saveAll(newCustomers);//有可能会因为保存客户信息导致保存任务信息错误
            }
        }
        DialTask dialTask = dialTaskRepository.save(task);
        log.info("任务状态修改成功.....");
        StrategyInfo strategyInfo = dialTask.getStrategyInfo();
        if (dialTask.getStatus().equals(TaskStatus.FINISH)
                && Objects.nonNull(strategyInfo)
                && dialTask.getRecoveryCount() < strategyInfo.getRecycleCount()) {
            log.info("开始自动回收.....");
            autoRecovery(dialTask);
            log.info("自动回收结束.....");
        }
    }

    /**
     * 自动回收，并创建对应的任务
     *
     * @param task
     */
    public void autoRecovery(DialTask task) {
        log.info("创建回收任务.....");
        DialTask dialTask = createNewTask(task);
        dialTask.setStatus(TaskStatus.READY);//状态
        dialTask.setCreateId(task.getCreateId());
        //获取日志信息
        BooleanBuilder builder = new BooleanBuilder();
        QTaskCustomer qTaskCustomer = QTaskCustomer.taskCustomer;
        StrategyInfo strategyInfo = task.getStrategyInfo();
        List<String> strategyIds = Arrays.asList(strategyInfo.getCategoryIds().split(","));
        builder.and(qTaskCustomer.attitude.id.in(strategyIds));
        builder.and(qTaskCustomer.dialTask.id.eq(task.getId()));
        builder.and(qTaskCustomer.blacklist.eq(Whether.NO));
        Iterator<TaskCustomer> iterator = taskCustomerRepository.findAll(builder).iterator();
        List<TaskCustomer> customerList = Lists.newArrayList(iterator);
        log.info("回收的客户信息：" + customerList);
        if (customerList != null && !customerList.isEmpty()) { //回收的客户信息有值时才回收
            dialTask.setCount(customerList.size());
            dialTask = dialTaskRepository.save(dialTask);
            log.info("保存创建回收的任务信息：" + dialTask);
            List<TaskCustomer> newList = new ArrayList<>();
            for (TaskCustomer taskCustomer : customerList) {
                TaskCustomer customer = new TaskCustomer();
                String id = UUID.randomUUID().toString();
                customer.setId(id);
                customer.setDialTask(dialTask);
                customer.setCreateTime(new Date());
                customer.setName(taskCustomer.getName());
                customer.setIdCard(taskCustomer.getIdCard());
                customer.setPhone(taskCustomer.getPhone());
                customer.setSex(taskCustomer.getSex());
                customer.setVariable(taskCustomer.getVariable());
                customer.setCompany(taskCustomer.getCompany());
                customer.setScene(dialTask.getScene());
                newList.add(customer);
            }
            taskCustomerRepository.saveAll(newList);
            log.info("回收的客户新信息：" + newList);
            socketService.sendTaskInfoById(dialTask.getId());
        }
    }

    public DialTask createNewTask(DialTask task) {
        DialTask dialTask = new DialTask();
        dialTask.setStatus(TaskStatus.NEW);//状态
        dialTask.setRecoveryCount(task.getRecoveryCount() + 1);
        dialTask.setName(task.getName() + "_recycle" + dialTask.getRecoveryCount());
        if (dialTask.getRecoveryCount() == 1) {
            dialTask.setInitId(task.getId());
        } else {
            dialTask.setInitId(task.getInitId());
        }
        dialTask.setParentId(task.getId());
        dialTask.setCreateTime(new Date());
        dialTask.setCreateId(task.getCreateId());
//        dialTask.setStartTime(task.getStartTime());
//        dialTask.setEndTime(task.getEndTime());
        dialTask.setCompany(task.getCompany());
        if (Objects.nonNull(task.getStrategyInfo())) {
            dialTask.setStrategyInfo(task.getStrategyInfo());
        }
        dialTask.setScene(task.getScene());
        Set<RobotInfo> set = new HashSet<>();
        for (RobotInfo robotInfo : task.getRobots()) {
            set.add(robotInfo);
        }
        dialTask.setRobots(set);
        return dialTask;
    }

    /**
     * 任务的删除
     *
     * @param id
     * @param sessionModel
     */
    public void deleteDialTaskById(String id, SessionModel sessionModel) {
        taskCustomerRepository.deleteByTaskId(id);
        dialTaskRepository.deleteById(id);
    }

    /**
     * csv 文件解析
     *
     * @param uploadFile 文件信息
     * @return 文件数据信息, 一个map为一行数据
     */
    public List<Map<String, String>> parseCSV(UploadFile uploadFile) throws Exception {
        List<Map<String, String>> list = new ArrayList<>();
        File file = this.uploadFileService.findOneFileById(uploadFile.getId());
        String fileName = file.getName();
        String fileType = fileName.substring(fileName.lastIndexOf("."));
        if(".xls".equals(fileType) || ".xlsx".equals(fileType)){
            list = ExcelUtil.getBankListByExcel(file);
        }else{
            list = this.readCSV(file.getPath());
        }
        return list;
    }


    private List<Map<String, String>> readCSV(String path) throws Exception {

        List<Map<String, String>> csvData = new ArrayList<>();
        CsvReader reader = new CsvReader(path, ',', Charset.forName("GBK"));
        // 跳过表头 如果需要表头的话，这句可以忽略
        reader.readHeaders();
        String[] csvZHNHeaders = reader.getHeaders();
        reader.readHeaders();
        String[] csvHead = reader.getHeaders();

        // 逐行读入除表头的数据
        while (reader.readRecord()) {
            Map<String, String> line = new HashMap<>();
            String[] csvLine = reader.getValues();
            for (int i = 0; i < csvLine.length; i++) {
                line.put(csvHead[i], csvLine[i]);
            }
            csvData.add(line);
        }
        reader.close();
        return csvData;
    }

    /**
     * 导入场景对应的数据模板
     *
     * @param response
     * @param sceId
     * @throws Exception
     */
    public void download(HttpServletResponse response, String sceId) throws Exception {
        SceneInfo sceneInfo = sceneInfoRepository.findById(sceId).orElseThrow(() -> new RuntimeException("场景信息不存在"));
        LinkedHashMap map = new LinkedHashMap();
        List exportData = new ArrayList<Map>();
        Map row = new LinkedHashMap<String, String>();
        List<Variable> list = new ArrayList<>(sceneInfo.getVariables());
        for (int i = 0; i < list.size(); i++) {
            map.put(String.valueOf(i + 1), list.get(i).getAlias());
            row.put(String.valueOf(i + 1), list.get(i).getName());
        }
        exportData.add(row);
        String fileName = sceneInfo.getName();
        File file = CSVUtils.createCSVFile(exportData, map, rootPath, fileName);
//        File file = new File(rootPath.concat(fileName).concat(".csv"));
        FileUtil.download(response, file);
//        CSVUtils.deleteFile(rootPath.concat(fileName));
    }


    /**
     * 任务的回收
     *
     * @param request
     */
    public void taskRecycle(TaskRecycleRequest request) {

        Optional<DialTask> optional = dialTaskRepository.findById(request.getTaskId());
        if (!optional.isPresent()) {
            throw new RuntimeException("回收的任务信息不存在");
        }
        DialTask task = optional.get();
        DialTask newTask = createNewTask(task);

//        BooleanBuilder builder = new BooleanBuilder();
//        QTaskCustomer qTaskCustomer = QTaskCustomer.taskCustomer;
//        builder.and(qTaskCustomer.dialTask.id.eq(request.getTaskId()));
//        builder.and(qTaskCustomer.attitude.id.in(request.getAttitudes()));
//        Iterator<TaskCustomer> iterator = taskCustomerRepository.findAll(builder).iterator();
        List<TaskCustomer> taskCustomers = taskCustomerRepository.getInfoByTaskIdAndAttitudes(request.getTaskId(), request.getAttitudes());
//                Lists.newArrayList(iterator);
        if (taskCustomers != null && !taskCustomers.isEmpty()) { //是否存在需要回收的信息
            newTask.setCount(taskCustomers.size());
            DialTask newTasks = dialTaskRepository.save(newTask);
            List<TaskCustomer> customers = new ArrayList<>();
            taskCustomers.forEach(c -> {
                TaskCustomer customer = new TaskCustomer();
                String id = UUID.randomUUID().toString();
                customer.setId(id);
                customer.setDialTask(newTasks);
                customer.setCreateTime(new Date());
                customer.setName(c.getName());
                customer.setPhone(c.getPhone());
                customer.setIdCard(c.getIdCard());
                customer.setSex(c.getSex());
                customer.setVariable(c.getVariable());
                customer.setScene(newTask.getScene());
                if(Objects.nonNull(newTask.getCompany())){
                    customer.setCompany(newTask.getCompany());
                }
                customers.add(customer);
            });
            taskCustomerRepository.saveAll(customers);
        }
    }



    /**
     * 任务取消功能
     *
     * @param taskId
     */
    public void saveTaskStatus(String taskId, TaskStatus status) {
        Optional<DialTask> optional = dialTaskRepository.findById(taskId);
        if (optional.isPresent()) {
            DialTask dialTask = optional.get();
            dialTask.setStatus(status);
            dialTaskRepository.save(dialTask);
        }
    }

    /**
     * 根据任务获取获取对应的客户信息
     *
     * @param taskId
     * @return
     */
    public List<Customer> fetchCustomerByTaskId(String taskId) {
        List<Customer> list = new ArrayList<>();
        BooleanBuilder builder = new BooleanBuilder();
        QTaskCustomer qTaskCustomer = QTaskCustomer.taskCustomer;
        builder.and(qTaskCustomer.dialTask.id.eq(taskId));
        builder.and(qTaskCustomer.blacklist.eq(Whether.NO));
        Iterator<TaskCustomer> iterator = taskCustomerRepository.findAll(builder).iterator();
        while (iterator.hasNext()) {
            TaskCustomer taskCustomer = iterator.next();
            Customer customer = new Customer();
            customer.setId(taskCustomer.getId());
            customer.setPhone(taskCustomer.getPhone());
            if (Objects.nonNull(taskCustomer.getAttitude()))
                customer.setAttitude(taskCustomer.getAttitude().getCode());
            customer.setStatus(taskCustomer.getStatus().toString());
            customer.setSex(taskCustomer.getSex().toString());
            customer.setVariable(taskCustomer.getVariable());
            list.add(customer);
        }
        return list;
    }
}
